#pragma once

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <unordered_map>
#include <fstream>
#include "comm.h"
#include "Log.h"

const std::string Sep = "\r\n";
const std::string LineSep = " ";
const std::string HeaderLineSep = ": ";
const std::string BlankLine = Sep;
const std::string defaulthomepage = "wwwroot";
const std::string http_version = "HTTP/1.0";
const std::string page404 = "wwwroot/404.html";
const std::string firstpage = "index.html";
using namespace LogMudule;
class HttpRequest
{
public:
    HttpRequest()
    {
    }
    ~HttpRequest()
    {
    }

    // 拆解kv
    bool ParseHeaderkv()
    {
        std::string key, value;
        for (auto &header : _req_header)
        {
            if (SplitString(header, HeaderLineSep, &key, &value))
            {
                _headerkv.insert(std::make_pair(key, value));
            }
        }
        return true;
    }
    // 请求报头
    bool ParseHeader(std::string &str)
    {
        std::string line;
        while (1)
        {
            bool n = ParseOneline(str, &line, Sep);
            if (n && !line.empty())
            {
                _req_header.push_back(line);
            }
            else if (n && line.empty())
            {
                _blank_line = Sep;
                break;
            }
            else
            {
                return false;
            }
        }
        ParseHeaderkv();
        return true;
    }
    bool IsHasArgs()
    {
        return _isexec;
    }
    // 反序列化
    void Deserialize(std::string &request_str)
    {
        if (ParseOneline(request_str, &_req_line, Sep))
        {
            ParseReLine(_req_line, LineSep);
            ParseHeader(request_str);
            _body = request_str;
        }
        if (_method == "POST")
        {
            _isexec = true; // 参数在正文
            _args = _body;
            _path = _url;
            LOG(LogLevel::DEBUG) << "POST: _path: " << _path;
            LOG(LogLevel::DEBUG) << "POST: _args: " << _args;
        }
        else if (_method == "GET")
        {
            auto pos = _url.find("?");
            if (pos != std::string::npos)
            {
                _isexec = true;
                // /login?name=zhang&passwd=123456
                _path = _url.substr(0, pos);
                _args = _url.substr(pos + 1);
                LOG(LogLevel::DEBUG) << "_path: " << _path;
                LOG(LogLevel::DEBUG) << "_args: " << _args;
            }
        }
    }
    // 打印
    void Print()
    {
        std::cout << "_method: " << _method << std::endl;
        std::cout << "_uri: " << _url << std::endl;
        std::cout << "_version: " << _version << std::endl;

        for (auto &kv : _headerkv)
        {
            std::cout << kv.first << " # " << kv.second << std::endl;
        }
        std::cout << "_blank_line: " << _blank_line << std::endl;
        std::cout << "_body: " << _body << std::endl;
    }
    std::string url()
    {
        return _url;
    }
    void SetUrl(std::string newurl)
    {
        _url = newurl;
    }
    std::string Path() { return _path; }
    std::string Args() { return _args; }
    std::string GetContent(const std::string path)
    {
        std::string content;
        std::ifstream in(path, std::ios::binary);
        if (!in.is_open())
        {
            return std::string();
        }
        in.seekg(0, in.end);
        int filesize = in.tellg();
        in.seekg(0, in.beg);

        content.resize(filesize);
        in.read((char *)content.c_str(), filesize);
        in.close();
        LOG(LogLevel::DEBUG) << "content length: " << content.size();
        return content;
    }
    std::string Suffix()
    {
        // _uri -> wwwroot/index.html wwwroot/image/1.jpg wwwroot/login.html
        auto pos = _url.rfind(".");
        if (pos == std::string::npos)
            return std::string(".html");
        else
            return _url.substr(pos);
    }

private:
    // 解析一行的参数
    void ParseReLine(std::string &str, const std::string sep)
    {
        (void)sep;
        std::stringstream ss(str);
        ss >> _method >> _url >> _version;
    }

private:
    std::string _req_line;                // 请求行
    std::vector<std::string> _req_header; // 请求行头部
    std::string _blank_line;              // 请求空白行
    std::string _body;                    // 请求正文

    // 反序列过程中，我们要提取的字段
    std::string _method;              // 请求的方法
    std::string _url;                 // 请求的域名
    std::string _path;                // 请求的路径
    std::string _args;                // 请求的参数
    std::string _version{"http/1.1"}; // http的版本
    std::unordered_map<std::string, std::string> _headerkv;
    bool _isexec = false;
};

class HttpResponse
{
public:
    HttpResponse() : _version(http_version), _blank_line(Sep)
    {
    }
    ~HttpResponse()
    {
    }
    void Build(HttpRequest &req)
    {
        std::string url = defaulthomepage + req.url();
        if (url.back() == '/')
        {
            // req.SetUrl(firstpage);
            url += firstpage;
        }
        LOG(LogLevel::DEBUG) << "---------客户端在请求" << req.url();
        req.Print();
        LOG(LogLevel::DEBUG) << "-------------------";
        _content = req.GetContent(url);
        if (_content.empty())
        {
            _status_code = 404;
            _content = req.GetContent(page404);
        }
        else
        {
            _status_code = 200;
        }
        _status_desc = Code2Desc(_status_code);
        if (!_content.empty())
        {
            SetHeader("Content-Length", std::to_string(_content.size()));
        }
        std::string mime_type = Suffix2Desc(req.Suffix());

        SetHeader("Content-Type", mime_type);
        _body = _content;
    }
    void SetCode(int code)
    {
        _status_code = code;
        _status_desc = Code2Desc(_status_code);
    }
    void SetBody(const std::string &body)
    {
        _body = body;
    }
    void SetHeader(const std::string &k, const std::string &v)
    {
        _header_kv[k] = v;
    }
    void SeriaLize(std::string *resp_str)
    {
        for (auto &header : _header_kv)
        {
            _resp_header.push_back(header.first + HeaderLineSep + header.second);
        }
        _resp_line = _version + LineSep + std::to_string(_status_code) + LineSep + _status_desc + Sep;
        *resp_str = _resp_line;
        for (auto &line : _resp_header)
        {
            *resp_str += (line + Sep);
        }
        *resp_str += _blank_line;
        *resp_str += _body;
    }

private:
    std::string Code2Desc(int code)
    {
        switch (code)
        {
        case 200:
            return "oK";
        case 404:
            return "NOT FOUND";
        default:
            return std::string();
        }
    }
    std::string Suffix2Desc(const std::string &suffix)
    {
        if (suffix == ".html")
            return "text/html";
        else if (suffix == ".jpg")
            return "application/x-jpg";
        else
            return "text/html";
    }

private:
    std::string _version{"http/1.1"};
    int _status_code;
    std::string _status_desc;
    std::string _content;
    std::unordered_map<std::string, std::string> _header_kv;

    // 最重要的部分，构建应答
    std::string _resp_line;
    std::vector<std::string> _resp_header;
    std::string _blank_line;
    std::string _body;
};